package com.fin.quant.web.service;

import com.fin.quant.web.vo.StockPriceItemVO;
import com.fin.quant.web.vo.StockPriceVO;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

@Service
public class StockPriceDataService {

    @Value("${stockModel.excel}")
    private String stockExcelPath;

    /**
     * 缓存文件
     */
    private volatile List<StockPriceVO> singletonStockPriceData;

    public List<StockPriceVO> getSingletonStockPriceData() throws IOException, InvalidFormatException {
        if (singletonStockPriceData != null) {
            return singletonStockPriceData;
        }
        synchronized (this) {
            if (singletonStockPriceData == null) {
                singletonStockPriceData = getAllStockPriceDataWithinSpecifiedPath();
            }
            return singletonStockPriceData;
        }
    }

    public void refreshFile() throws IOException, InvalidFormatException {
        synchronized (this) {
            singletonStockPriceData = getAllStockPriceDataWithinSpecifiedPath();
        }
    }

    public void refreshFile(File stockFile) throws IOException, InvalidFormatException {
        synchronized (this) {
            singletonStockPriceData = getStockPriceDataWithPath(stockFile);
        }

    }

    private List<StockPriceVO> getAllStockPriceDataWithinSpecifiedPath() throws IOException, InvalidFormatException {
        return getStockPriceDataWithPath(new File(stockExcelPath));
    }

    private List<StockPriceVO> getStockPriceDataWithPath(File stockFile) throws IOException, InvalidFormatException {
        Workbook wb = WorkbookFactory.create(stockFile);

        List<StockPriceVO> stockPriceVOList = Lists.newArrayList();

        wb.sheetIterator().forEachRemaining(sheet -> {
            Iterator<Row> rowIterator = sheet.rowIterator();
            //跳过标题
            rowIterator.next();
            Row row;

            List<StockPriceItemVO> items = Lists.newArrayList();
            while ((row = rowIterator.next()) != null) {
                if (row.getRowNum() >= sheet.getLastRowNum()) {
                    break;
                }
                StockPriceItemVO item = new StockPriceItemVO();

                String date = getCellStringValue(row.getCell(0));
                String predictClose = getCellStringValue(row.getCell(1));
                String realClose = getCellStringValue(row.getCell(2));
                String modelVersion = getCellStringValue(row.getCell(3));
                if (StringUtils.isBlank(date)) {
                    break;
                }

                item.setDate(date);
                if (StringUtils.isNotBlank(predictClose)) {
                    item.setPredictClose(Double.parseDouble(predictClose));
                }
                if (StringUtils.isNotBlank(realClose)) {
                    item.setRealClose(Double.parseDouble(realClose));
                }
                if (item.getPredictClose() != null && item.getRealClose() != null) {
                    item.setNegativeLoss(String.format("%.2f", -Math.abs(item.getPredictClose() - item.getRealClose())));
                    item.setNegativePercentLoss(String.format("%.4f", Double.parseDouble(item.getNegativeLoss()) / item.getPredictClose() * 100) + "%");
                }
                item.setModelVersion(modelVersion);
                items.add(item);
            }
            StockPriceVO stockPriceVO = new StockPriceVO();
            stockPriceVO.setName(sheet.getSheetName());
            stockPriceVO.setLoading(false);
            stockPriceVO.setTableData(items);
            stockPriceVOList.add(stockPriceVO);
        });

        return stockPriceVOList;
    }

    private String getCellStringValue(Cell cell) {
        if (cell == null) {
            return null;
        }
        cell.setCellType(CellType.STRING);
        return cell.getStringCellValue();
    }

    public static void main(String[] args) {
        System.out.println(String.format("%.4f", 1.2222222));
    }
}

